#include "semanticCube.h"
#include<iostream>
using namespace std;
/*
 TYPES
	int -> 0    float -> 1    boolet -> 2    char -> 3    list -> 4
 OPERATIONS	
	+  -> 0     -  -> 1      *  -> 2     / -> 3     >  -> 4     <  -> 5    
    <> -> 6	    :< -> 7     :>  -> 8    :{ -> 9    AND -> 10    OR -> 11    
	:O -> 12 	:D -> 13    NOT -> 14    NEG -> 15
 */

semanticCube::semanticCube() {
	for(int i=0;i<5;i++){
		for(int j=0;j<5;j++){
			for(int k=0;k<16;k++){
				if(i == 0){
					if(j == 0){
						if(k == 0 || k == 1 || k == 2 || k == 13 || k == 15) {cube[i][j][k] = 0; continue;}
						if(k == 3){ cube[i][j][k] = 1; continue;}
						if(k == 4 || k == 5 || k == 6 || k == 7 || k == 8 || k == 9){ cube[i][j][k] = 2; continue;}
					}
					if(j == 1){
						if(k == 0 || k == 1 || k == 2 || k == 3){ cube[i][j][k] = 1; continue;}
						if(k == 4 || k == 5 || k == 6 || k == 7 || k == 8 || k == 9){ cube[i][j][k] = 2; continue;}
					}
				}
				if(i == 1){
					if(j == 0){
						if(k == 0 || k == 1 || k == 2 || k == 3 || k == 13){ cube[i][j][k] = 1; continue;}
						if(k == 4 || k == 5 || k == 6 || k == 7 || k == 8 || k == 9){ cube[i][j][k] = 2; continue;}
					}
					if(j==1){
						if(k == 0 || k == 1 || k == 2 || k == 3 || k == 13 || k == 15){ cube[i][j][k] = 1; continue;}
						if(k == 4 || k == 5 || k == 6 || k == 7 || k == 8 || k == 9){ cube[i][j][k] = 2; continue;}
					}
				}
				if(i == 2 && j == 2)
					if(k == 6 || k == 9 || k == 10 || k == 11 || k == 13 || k == 14){ cube[i][j][k] = 2; continue;}
				if(i == 3 && j == 3){
					if(k == 6 || k == 9){ cube[i][j][k] = 2; continue;}
					if(k == 13){ cube[i][j][k] = 3; continue;}
				}
				if(i == 4 && j == 4 && k == 13){ cube[i][j][k] = 4; continue;}
				if(k == 12){ cube[i][j][k] = 4; continue;}
				cube[i][j][k] = 5;
			}
		}
	}
}

const wchar_t* semanticCube::ask(const wchar_t* type1, const wchar_t* oper, const wchar_t* type2) {
	int t1 = lettersToNumber(type1);
	int t2 = lettersToNumber(type2);
	int op = operatorToNumber(oper);

	if (t1 == 5) {
		if (t2 == 5) {
			if (type1 == type2) {
				if (op == 13) {
					return type1;
				} else {
					return L"Error1"; //ambos objetos del mismo tipo, pero operacion no soportada
				}
			} else {
				return L"Error2"; //ambos objetos, diferente tipo
			}
		} else {
			return L"Error3"; //uno es objeto pero el otro no
		}
	} else if (t2 == 5) {
		if (t1 == 5) {
			if (type1 == type2) {
				if (op == 13) {
					return type1;
				} else {
					return L"Error1";
				}
			} else {
				return L"Error2";
			}
		} else {
			return L"Error3";
		}
	} else {
		if (op < 20) {
			return numberToLetters(verify(t1,t2,op));
		} else {
			return L"Error4"; //operador no existente
		}
	}
}

int semanticCube::lettersToNumber(const wchar_t* type) {
	if (!wcscmp(type, L"int")) {
		return 0;
	} else if (!wcscmp(type, L"float")) {
		return 1;
	} else if (!wcscmp(type, L"boolet")) {
		return 2;
	} else if (!wcscmp(type, L"char")) {
		return 3;
	} else if (!wcscmp(type, L"list")) {
		return 4;
	} else {
		return 5;
	}
}

int semanticCube::operatorToNumber(const wchar_t* type) {
	if (!wcscmp(type, L"+")) {
		return 0;
	} else if (!wcscmp(type, L"-")) {
		return 1;
	} else if (!wcscmp(type, L"*")) {
		return 2;
	} else if (!wcscmp(type, L"/")) {
		return 3;
	} else if (!wcscmp(type, L">")) {
		return 4;
	} else if (!wcscmp(type, L"<")) {
		return 5;
	} else if (!wcscmp(type, L"<>")) {
		return 6;
	} else if (!wcscmp(type, L":<")) {
		return 7;
	} else if (!wcscmp(type, L":>")) {
		return 8;
	} else if (!wcscmp(type, L":{")) {
		return 9;
	} else if (!wcscmp(type, L"AND")) {
		return 10;
	} else if (!wcscmp(type, L"OR")) {
		return 11;
	} else if (!wcscmp(type, L":O")) {
		return 12;
	} else if (!wcscmp(type, L":D")) {
		return 13;
	} else if (!wcscmp(type, L"NOT")) {
		return 14;
	} else if (!wcscmp(type, L"NEG")) {
		return 15;
	} else {
		return 20;
	}
}

const wchar_t* semanticCube::numberToLetters(int type) {
	if (type == 0) {
		return L"int";
	} else if (type == 1) {
		return L"float";
	} else if (type == 2) {
		return L"boolet";
	} else if (type == 3) {
		return L"char";
	} else if (type == 4){
		return L"list";
	} else {
		return L"Error"; //operacion no soportada
	}
}

int semanticCube::verify(int type1, int type2, int operation) {
	if(type2 == -1)
		return cube[type1][type1][operation];
	return cube[type1][type2][operation];
}
